﻿// tut_b1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
// v1 2024-1-13 10：00 经过实验通过集成ElevationLayer，动态修改HeightData，只能一次性改变
//    地图高度，除非切换到新的区域重新生成瓦片的时候才能按照新的scale值重新生成高程，否则基本没法动态修改高程，
//    主要是修改高程后它不刷新。
#include <osgViewer/viewer>
#include <osgEarth/Notify>
#include <osgEarth/EarthManipulator>
#include <osgEarth/MapNode>
#include <osgEarth/Threading>
#include <osgEarth/ShaderGenerator>
#include <osgDB/ReadFile>
#include <osgGA/TrackballManipulator>
#include <osgUtil/Optimizer>
#include <iostream>
#include <osgEarth/Metrics>
#include "osgEarth/GDAL";
#include "osgEarth/Controls"
#include "osgEarth/XYZ"
#include "MyElevationLayer.h"//自定义高程图层
using namespace osgEarth;
using namespace osgEarth::Util;
#include <iostream>
#include "osgEarthDrivers\sky_simple\SimpleSkyNode"//for the sky
#include "osgEarthDrivers\sky_simple\SimpleSkyOptions"//for the sky
using namespace std;
MyElevationLayer* g_elevationLayer = 0;
osgEarth::Util::Controls::LabelControl* g_labelHeight = 0;
osgEarth::MapNode* g_mapNode = 0;
struct MyControlHandler :public osgEarth::Util::Controls::ControlEventHandler {
	virtual void onValueChanged(osgEarth::Util::Controls::Control* control, float value) {
		char buff[64];
		sprintf(buff, "heightScale:%5.2f", value);
		g_labelHeight->setText(string(buff));
		g_elevationLayer->setScale(value);//更新高程放大系数
		g_elevationLayer->dirty();//对于已绘制瓦片无效
		g_mapNode->getTerrain()->notifyMapElevationChanged();//对于已绘制瓦片无效too
	}
};
//生成GUI
osgEarth::Util::Controls::ControlCanvas* makeGUI() {
	//Event handler构建一个共享的Handler对象，当然不同Control可以设置单独的Handler
	osg::ref_ptr<MyControlHandler> controlHandler = new MyControlHandler;
	//UI Canvase
	osgEarth::Util::Controls::ControlCanvas* canvas = new osgEarth::Util::Controls::ControlCanvas();
	//container
	osgEarth::Util::Controls::VBox* vbox = new osgEarth::Util::Controls::VBox(
		osgEarth::Util::Controls::Container::Alignment::ALIGN_LEFT,
		osgEarth::Util::Controls::Container::Alignment::ALIGN_TOP,
		osgEarth::Util::Controls::Gutter(2, 2, 2, 2),
		5 //the margin between controls inside.
	);
	vbox->setBackColor(0.8, 0.8, 0.8, 0.5);
	//label for heightScale
	osgEarth::Util::Controls::LabelControl* labelHeight = new osgEarth::Util::Controls::LabelControl("heightScale:1");
	vbox->addControl(labelHeight);
	g_labelHeight = labelHeight;
	//slider for height scale
	osgEarth::Util::Controls::HSliderControl* sliderHeight = new osgEarth::Util::Controls::HSliderControl(
		1,  //min
		30, //max
		1,  //init
		controlHandler.get());
	sliderHeight->setUserValue("ID", 1);
	sliderHeight->setWidth(200);
	sliderHeight->setHeight(20);
	vbox->addControl(sliderHeight);
	canvas->addControl(vbox);
	return canvas;
}
int main()
{
	osgEarth::initialize();
	//create a viewer
	osgViewer::Viewer viewer;
	viewer.setUpViewInWindow(0, 100, 800, 600);
	viewer.setReleaseContextAtEndOfFrameHint(false);
	//set camera manipulator
	viewer.setCameraManipulator(new EarthManipulator);
	osgEarth::Map* map = new osgEarth::Map();
	//layer
	GDALImageLayer* layer1 = new GDALImageLayer();
	layer1->setURL(osgEarth::URI("E:/coding/osgearth2023/osgearth3.4/data/world.tif"));
	map->addLayer(layer1);
	//Custom Elevation
	MyElevationLayer* myElevation = new MyElevationLayer;
	myElevation->setURL(osgEarth::URI("E:/coding/osgearth2023/osgearth3.4/data/dem_cog_0.0833f.tif"));
	myElevation->setDataVariance(osg::Object::DataVariance::DYNAMIC);//this is not working for update height.
	map->addLayer(myElevation);
	g_elevationLayer = myElevation;
	osg::ref_ptr<osgEarth::MapNode> mapNode = new osgEarth::MapNode(map);
	//天空效果
	{
		//SkyOptions options;
		osgEarth::SimpleSky::SimpleSkyOptions options;
		options.quality() = SkyOptions::QUALITY_DEFAULT;
		options.ambient() = 0.001;//控制环境光强度
		options.exposure() = 10.f;//控制白天的亮度
		options.atmosphereVisible() = true;//大气层厚度是否可见
		options.atmosphericLighting() = true;//大气散射光是否可见
		options.sunVisible() = true;
		options.moonVisible() = true;
		options.starsVisible() = true;
		options.usePBR() = true;
		options.set_hours(20);
		//添加天空模型
		mapNode->addExtension(Extension::create("sky_simple", options));//这里不能使用addChild, Extension是一种更复杂的对象
		//set black background color
		viewer.getCamera()->setClearColor(osg::Vec4(0, 0, 0, 1));//设置宇宙背景颜色为黑色
	}
	//controls
	mapNode->addChild(makeGUI());
	g_mapNode = mapNode;
	viewer.setSceneData(mapNode);
	return Metrics::run(viewer);
}